using Godot;
using Godot.Collections;
using System;

public partial class HpManager : Node
{
    [Signal]
    public delegate void PlayerDeadEventHandler();

    [Export]
    public int CurrentHP
    {
        get => _currentHP;
        set
        {
            if (_ready) SwitchHP(value);
        }
    }
    private int _currentHP = 3;

    [Export]
    public float FlashLightenParam { get; set; } = 0.6f;
    [Export]
    public float FlashDarkenParam { get; set; } = 0.4f;

    [Export]
    public Array<Vector3> ComposerConfig { get; set; }
    [Export]
    public Array<Vector3I> LightLayerConfig { get; set; }

    // private values
    private CameraShaderControl _cameraShader;
    private PlayerLightLayer _lightLarge, _lightMedium, _lightSmall;
    private PlayerParticleEmitter _particleEmitter;
    private bool _ready = false;


    public override void _Ready()
    {
        _cameraShader = GetNode<NodeReferenceMap>(Constants.NodeRefMapPath).CameraShader;
        _lightLarge = GetNode<PlayerLightLayer>("../Light/LightLayerL");
        _lightMedium = GetNode<PlayerLightLayer>("../Light/LightLayerM");
        _lightSmall = GetNode<PlayerLightLayer>("../Light/LightLayerS");
        _particleEmitter = GetNode<PlayerParticleEmitter>("../ParticleEmitter");

        _ready = true;
        SwitchHP(_currentHP);
    }
    
    // Export interfaces
    public void SetHP(int targetHP)
    {
        SwitchHP(targetHP, false);
    }

    private void SwitchHP(int targetHP, bool allowParticle = true)
    {
        // Clamp input
        targetHP = Mathf.Clamp(targetHP, 0, 3);

        if (allowParticle)
        {
            // Emit particle
            if (targetHP > _currentHP)
            {
                _cameraShader.FlashLightenVisual(FlashLightenParam);
                _particleEmitter.CreateHealingParticle();
            }
            else if (targetHP < _currentHP)
            {
                _cameraShader.FlashDarkenVisual(FlashDarkenParam);
                _particleEmitter.CreateDamageParticle();
            }
        }
        _currentHP = targetHP;

        // Set Visuals
        if (_currentHP <= 0)
        {
            EmitSignal(SignalName.PlayerDead);
            _currentHP = 0;
        }
        SyncComposer(ComposerConfig[_currentHP]);
        SyncLightLayer(LightLayerConfig[_currentHP]);
    }

    private void SyncComposer(Vector3 config)
    {
        _cameraShader.DarknessBase = config.X;
        _cameraShader.DarknessScaler = config.Y;
        _cameraShader.ColorDiffuseStrength = config.Z;
    }

    private void SyncLightLayer(Vector3I config)
    {
        _lightSmall.LightVisible = config.X > 0;
        _lightMedium.LightVisible = config.Y > 0;
        _lightLarge.LightVisible = config.Z > 0;
    }
}
